#ifndef RTE_KB1285_FDB_TSL_H
#define RTE_KB1285_FDB_TSL_H

#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <stdio.h>
#include <time.h>
#include <fdb_cfg.h>
#include "fdb_def.h"
#include "fdb_low_lvl.h"

/* magic word(`T`, `S`, `L`, `5`) */
#ifndef SECTOR_MAGIC_WORD
#define SECTOR_MAGIC_WORD 0x3A4C5354
#endif


#define SECTOR_HDR_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct sector_hdr_data_tsl)))
#define LOG_IDX_DATA_SIZE (FDB_WG_ALIGN(sizeof(struct log_idx_data)))
#define LOG_IDX_TS_OFFSET ((unsigned long)(&((struct log_idx_data *)0)->time))
#define LOG_IDX_ID_OFFSET ((unsigned long)(&((struct log_idx_data *)0)->id))
#define SECTOR_MAGIC_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->magic))
#define SECTOR_START_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->start_time))
#define SECTOR_END0_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[0].time))
#define SECTOR_END0_ID_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[0].last_id))
#define SECTOR_END0_IDX_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[0].index))
#define SECTOR_END0_STATUS_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[0].status))
#define SECTOR_END1_TIME_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[1].time))
#define SECTOR_END1_ID_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[1].last_id))
#define SECTOR_END1_IDX_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[1].index))
#define SECTOR_END1_STATUS_OFFSET ((unsigned long)(&((struct sector_hdr_data_tsl *)0)->end_info[1].status))


#define FDB_LOG_TAG "[tsl]"
#define TSL_STATUS_TABLE_SIZE FDB_STATUS_TABLE_SIZE(FDB_TSL_STATUS_NUM)
/* the next address is get failed */
#define FAILED_ADDR                              0xFFFFFFFF


#define db_lock(db)                                                            \
do {                                                                       \
if (((fdb_db_t)db)->lock) ((fdb_db_t)db)->lock((fdb_db_t)db);          \
} while(0);

#define db_unlock(db)                                                          \
do {                                                                       \
if (((fdb_db_t)db)->unlock) ((fdb_db_t)db)->unlock((fdb_db_t)db);      \
} while(0);

#define _FDB_WRITE_STATUS(db, addr, status_table, status_num, status_index, sync)    \
do {                                                                       \
result = _fdb_write_status((fdb_db_t)db, addr, status_table, status_num, status_index, sync);\
if (result != FDB_NO_ERR) return result;                               \
} while(0);

#define FLASH_WRITE(db, addr, buf, size, sync)                                 \
do {                                                                       \
result = _fdb_flash_write((fdb_db_t)db, addr, buf, size, sync);        \
if (result != FDB_NO_ERR) return result;                               \
} while(0);


/* time series log node index data */
struct log_idx_data {
    uint8_t status_table[TSL_STATUS_TABLE_SIZE]; /**< node status, @see fdb_tsl_status_t */
    fdb_time_t time;                             /**< node timestamp */
    uint32_t id;
    uint32_t log_len;                            /**< node total length (header + name + value), must align by FDB_WRITE_GRAN */
    uint32_t log_addr;                           /**< node address */
};
typedef struct log_idx_data *log_idx_data_t;

struct query_count_args {
    fdb_tsl_status_t status;
    size_t count;
};

struct check_sec_hdr_cb_args {
    fdb_tsdb_t db;
    bool check_failed;
    size_t empty_num;
    uint32_t empty_addr;
};


#ifdef __cplusplus
extern "C" {
#endif
#define db_name(db) (((fdb_db_t)db)->name)
#define db_init_ok(db) (((fdb_db_t)db)->init_ok)
#define db_sec_size(db) (((fdb_db_t)db)->sec_size)
#define db_max_size(db) (((fdb_db_t)db)->max_size)

struct sector_hdr_data_tsl {
    uint8_t status[FDB_STORE_STATUS_TABLE_SIZE]; /**< sector store status @see fdb_sector_store_status_t */
    uint32_t magic;                              /**< magic word(`T`, `S`, `L`, `0`) */
    fdb_time_t start_time;                       /**< the first start node's timestamp */
    struct {
        fdb_time_t time;                       /**< the last end node's timestamp */
        uint32_t index;                        /**< the last end node's index */
        uint32_t last_id;
        uint8_t status[TSL_STATUS_TABLE_SIZE]; /**< end node status, @see fdb_tsl_status_t */
    } end_info[2];
    uint32_t reserved;
};
//typedef struct sector_hdr_data_tsl *sector_hdr_data_t;

fdb_err_t read_sector_info(fdb_tsdb_t db, uint32_t addr, tsdb_sec_info_t sector, bool traversal);

fdb_err_t read_tsl(fdb_tsdb_t db, fdb_tsl_t tsl);

uint32_t get_next_tsl_addr(tsdb_sec_info_t sector, fdb_tsl_t pre_tsl);

uint32_t get_next_sector_addr(fdb_tsdb_t db, tsdb_sec_info_t pre_sec, uint32_t traversed_len);

uint32_t get_last_sector_addr(fdb_tsdb_t db, tsdb_sec_info_t pre_sec, uint32_t traversed_len);

#ifdef __cplusplus
};
#endif
#endif //RTE_KB1285_FDB_TSL_H
